package com.ruoyi.common.utils.report;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.ruoyi.common.utils.report.pic.RadarUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.poi.ooxml.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.drawingml.x2006.picture.CTPicture;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class ReportUtil {

    public static void main(String[] args) {
        String tmpl = "E:\\IDEA\\RuoYi-Vue\\uploadPath\\reporttmpl\\tpml-v2.0.docx";

        //要替换的map，key为占位符，value为要被替换的值
        HashMap<String, String> textMap = new HashMap<>();
        textMap.put("${company}", "金马投资公司");
        textMap.put("${name}", "陈玉");
        textMap.put("${idNumber}", "642152152542151254");
        textMap.put("${phone}", "13358445878");
        textMap.put("${address}", "北京市顺义区张家巷14号");
        //textMap.put("${pic2}", "企业已充分认识到智能制造的重要性，但需要培养和引进智能制造发展所需的人员，包括制定有针对智能制造的人才培养体系，制定有针对智能制造的考核机制，及时有效地使员工获取新技能和资格。建议企业建立智能制造统筹规划能力的团队，实施智能制造的技术人员必须具备IT基础、数据分析、信息安全、系统运维、设备维护、编程调试等能力。另建议企业建立知识管理体系，通过信息技术手段管理人员贡献的知识和经验。");

        HashMap<String, HashMap<String, Double>> gscores = new HashMap<>();
        HashMap<String, Double> scores = new HashMap<>();
        scores.put("人员", 60.0);
        scores.put("组织", 70.0);
        scores.put("战略", 80.0);
        scores.put("结构", 90.0);
        gscores.put("人员", scores);
        HashMap<String, HashMap<String, Double>> gscores1 = new HashMap<>();
        HashMap<String, Double> scores1 = new HashMap<>();
        scores1.put("人员1", 60.0);
        scores1.put("组织1", 70.0);
        scores1.put("战略1", 80.0);
        scores1.put("结构1", 90.0);
        scores1.put("人员", 60.0);
        scores1.put("组织", 70.0);
        scores1.put("战略", 80.0);
        scores1.put("结构", 90.0);
        gscores1.put("人员2", scores1);
//        Map<String, InputStream> picMap = new HashMap<>();
//        try {
//            InputStream pic1 = RadarUtil.bufferedImageToInputStream(gscores);
//
//            picMap.put("${pic1}", pic1);
//            InputStream pic2 = RadarUtil.bufferedImageToInputStream(gscores1);
//
//            picMap.put("${pic2}", pic2);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }


        String[] header = {"姓名", "性别", "部门", "工号"};
        List<String> hlist = new ArrayList<>(Arrays.asList(header));

        String[][] datas =
                {
                        new String[]{ "综合", "一级"},
                        new String[]{ "综合", "一级"},
                        new String[]{ "技术", "二级"},
                        new String[]{ "销售", "二级"},
                        new String[]{ "后勤", "三级"},
                };

        List<List<String>> dlist = new ArrayList<>();
        for (String[] data : datas) {
            List<String> tlist = new ArrayList<>(Arrays.asList(data));
            dlist.add(tlist);
        }





        HashMap<String, List<List<String>>> items = new HashMap<>();

        items.put("well", dlist);
        items.put("done", dlist);
        items.put("undo", dlist);
        HashMap<String, HashMap<String, List<List<String>>>> ssproblem1 = new HashMap<>();
        HashMap<String, HashMap<String, List<List<String>>>> ssproblem2 = new HashMap<>();
        HashMap<String, HashMap<String, List<List<String>>>> ssproblem3 = new HashMap<>();
        HashMap<String, HashMap<String, List<List<String>>>> ssproblem4 = new HashMap<>();

        HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>> sproblem = new HashMap<>();
        HashMap<String,HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>> problems = new HashMap<>();


        String ps="{\"制造\":{\"设计\":{\"制造\":{\"imperfect\":[],\"perfect\":[[\" 已经基于产品设计数据开展工艺设计和优化？\",\"一级\"],[\" 已经制定工艺设计过程相关规范，并有效执行？\",\"一级\"],[\" 已经已建立工艺文档或数据的管理机制，能够对工艺数据进行记录、查阅和执行？\",\"一级\"],[\" 已经基于计算机辅助开展工艺设计和优化？\",\"二级\"],[\" 已经基于典型产品或特征建立工艺模板，实现关键工艺设计信息重用？\",\"二级\"]],\"undone\":[[\" 尚未实现工艺不同专业之间的并行设计？\",\"二级\"],[\" 尚未建有工艺设计管理系统？\",\"三级\"],[\"已建立的工艺设计系统可实现\",\"三级\"],[\" 尚未建立典型制造工艺流程、参数、资源等关键要素的知识库，并能以结构化的形式展现、查询和更新？\",\"三级\"],[\" 尚未基于数字化模型实现制造工艺关键环节的仿真分析和迭代优化？\",\"三级\"],[\" 尚未实现工艺设计与产品设计之间的信息交互，并行协同？\",\"三级\"]]}},\"生产\":{\"制造\":{\"imperfect\":[],\"perfect\":[[\" 已经建立企业能源管理制度，并开展主要能源的数据采集和计量？\",\"一级\"],[\" 已经通过信息技术手段对主要能源的产生、消耗点开展数据采集和计算？\",\"二级\"],[\" 已经建立水、电、气等重点能源的动态监控和计量？\",\"二级\"],[\" 已经实现对重点高耗能设备、系统等动态运行监控？\",\"二级\"],[\" 已经对有节能优化需求的设备开展实时计量，并基于计量结果进行改造？\",\"二级\"],[\" 已经对高能耗设备能耗数据进行统计分析，制定合理的能耗评价指标？\",\"三级\"],[\" 已经已建立能源管理系统，对能源输送、存储、转化、使用等环节进行全面监控，进行能源使用与生产活动匹配，并实现能源调度？\",\"三级\"],[\" 已经能实现能源数据与其他系统数据共享，为业务管理系统和决策支持系统提供能源数据？\",\"三级\"]],\"undone\":[]}},\"物流\":{\"物流\":{\"imperfect\":[],\"perfect\":[[\" 已经通过电话、短信等形式反馈运输配送关键节点信息给管理人员？\",\"二级\"],[\" 已经通过仓储（罐区）管理系统和运输管理系统集成，整合出库和运输过程？\",\"三级\"]],\"undone\":[[\" 尚未根据运输订单和经验，制定运输计划并配置调度？\",\"一级\"],[\" 尚未对车辆和驾驶员进行统一管理？\",\"一级\"],[\" 尚未对物流信息进行简单跟踪？\",\"一级\"],[\" 尚未通过运输管理系统实现订单、运输计划、运力资源、调度等的管理？\",\"二级\"],[\" 尚未实现运输配送关键节点信息跟踪，并通过信息系统将信息反馈给客户？\",\"三级\"],[\" 尚未通过运输管理系统，实现拆单和拼单等功能？\",\"三级\"]]}},\"服务\":{\"制造\":{\"imperfect\":[],\"perfect\":[[\" 已经通过信息技术手段对产品使用信息进行统计，并反馈给相关部门？\",\"二级\"],[\" 产品已经具有数据采集、存储、网络通信功能？\",\"三级\"]],\"undone\":[[\" 尚未制定产品服务规范，并有效开展现场运维及远程运维指导服务？\",\"一级\"],[\" 尚未对产品故障信息进行统计，并反馈给设计、生产、销售部门？\",\"一级\"],[\" 尚未具有产品故障知识库和维护方法知识库，为服务人员提供现场运维和远程运维操作指导？\",\"二级\"],[\"尚未具有产品服务系统，该系统具有哪些功能？（可多选）\",\"三级\"]]}},\"销售\":{\"销售\":{\"imperfect\":[],\"perfect\":[[\" 已经对销售订单、销售合同、分销商、客户等信息进行统计和管理？\",\"一级\"]],\"undone\":[[\" 尚未基于市场信息和销售历史数据（如区域、型号、产品定位、数量等），通过人工方式进行市场预测，制定销售计划？\",\"一级\"],[\" 尚未通过信息系统编制销售计划，实现销售计划、订单、销售历史数据库的管理？\",\"二级\"],[\" 尚未通过信息技术手段实现分销商、客户静态信息和动态信息的管理？\",\"二级\"],[\" 尚未根据数据模型进行市场预测，生成销售计划？\",\"三级\"],[\" 尚未已与采购、生产、物流等业务集成，实现客户实际需求拉动采购、生产和物流计划？\",\"三级\"]]}}},\"技术\":{\"数据\":{\"技术\":{\"imperfect\":[[\" 部分完成已采集业务活动所需的数据？\",\"一级\"]],\"perfect\":[[\" 已经已实现数据及分析结果在部门内在线共享?\",\"二级\"]],\"undone\":[[\" 尚未已基于经验对数据进行分析？\",\"一级\"],[\" 数据采集的方式是？（可以多选）\",\"二级\"],[\" 基于经验的数据分析对业务活动尚未有帮助？\",\"二级\"],[\" 尚未采用传感技术实现制造关键环节数据的自动采集？\",\"三级\"],[\" 尚未已建立统一的数据编码、数据交换格式和规则等，整合数据资源，支持跨部门的业务协调？\",\"三级\"],[\" 尚未已实现数据及分析结果跨部门内在线共享？\",\"三级\"]]}},\"集成\":{\"技术\":{\"imperfect\":[[\" 企业部分完成已开展系统集成规划，包含哪些方面？\",\"二级\"]],\"perfect\":[],\"undone\":[[\" 企业尚未已意识到系统集成的必要性？\",\"一级\"],[\" 尚未已实现关键业务活动设备、系统间的集成？\",\"二级\"],[\" 尚未已形成完整的系统集成架构？\",\"三级\"],[\" 尚未具有设备、控制系统与软件系统间集成的技术规范，包括异构协议的集成规范、工业软件的接口规范等？\",\"三级\"],[\" 尚未已通过中间件工具、数据库接口、集成平台等方式，实现跨业务活动设备、系统间的集成？\",\"三级\"]]}},\"信息安全\":{\"技术\":{\"imperfect\":[],\"perfect\":[[\" 已经已在工业主机上进行安全配置和补丁管理？\",\"二级\"]],\"undone\":[[\" 尚未已成立信息安全协调小组？\",\"一级\"],[\" 尚未已制定信息安全管理规范，并已执行？\",\"一级\"],[\" 尚未定期对关键工业控制系统开展信息安全风险评估？\",\"二级\"],[\" 尚未已在工业主机上安装正规的工业防病毒软件？\",\"二级\"],[\" 工业控制网络边界尚未具有边界防护能力？\",\"三级\"],[\" 工业控制设备的远程访问尚未进行安全管理和加固？\",\"三级\"]]}}},\"人员\":{\"组织战略\":{\"人员\":{\"imperfect\":[[\" 企业部分完成已制定智能制造发展规划？\",\"一级\"],[\" 企业部分完成对发展制造所需的资源进行投资？\",\"一级\"],[\" 企业已制定的智能制造发展战略包含以下哪些项目？（可多选）\",\"二级\"],[\" 企业优化岗位结构的情况（可多选）\",\"三级\"]],\"perfect\":[[\" 企业持续优化战略的证明资料列表\",\"三级\"]],\"undone\":[[\" 企业尚未已针对智能制造发展战略形成具体的实施计划？\",\"二级\"],[\" 企业尚未已明确智能制造责任部门？\",\"二级\"],[\" 企业尚未已明确智能制造各关键岗位负责人及其职责？\",\"二级\"],[\" 企业尚未对实施计划的执行情况进行监控与测评？\",\"三级\"]]}},\"人员技能\":{\"人员\":{\"imperfect\":[],\"perfect\":[[\" 企业已经已充分认识到智能制造的重要性？\",\"一级\"],[\" 企业已经已建立知识管理体系，可通过信息技术手段管理人员贡献的知识和经验？\",\"三级\"]],\"undone\":[[\" 企业尚未已培养和引进智能制造发展所需的人员？\",\"一级\"],[\" 企业培养人才的情况是？（可多选）\",\"二级\"],[\" 企业尚未有智能制造统筹规划能力的个人或团队？\",\"二级\"],[\" 企业实施智能制造的技术人员具备以下哪几项能力？（可多选）\",\"二级\"],[\" 企业尚未有创新管理机制？\",\"三级\"]]}}},\"资源\":{\"装备\":{\"资源\":{\"imperfect\":[],\"perfect\":[[\" 已经在关键工序应用自动化设备？\",\"一级\"],[\" 关键工序设备已经具备数据管理、模拟加工、图形化编程等人机交互功能？\",\"三级\"],[\" 已经已建立关键工序设备的三维模型库？\",\"三级\"]],\"undone\":[[\" 尚未对关键设备已形成技改方案？\",\"一级\"],[\" 尚未在关键工序中应用数字化设备？\",\"二级\"],[\" 关键工序设备具备哪些标准统信接口？（可以多选）\",\"二级\"],[\" 关键工序设备具备支持的主流通信协议？（可以多选）\",\"二级\"]]}},\"网络\":{\"资源\":{\"imperfect\":[],\"perfect\":[[\" 企业已经实现办公网络覆盖？\",\"一级\"],[\" 企业已经实现工业控制网络和生产网络覆盖？\",\"二级\"],[\" 否已建立工业控制网络、生产网络、办公网络的防护措施，包括但不限于网络安全隔离、授权访问等手段？\",\"三级\"],[\" 网络已经具有远程配置功能？\",\"三级\"],[\" 网络已经具备带宽、规模、关键节点的扩充和升级功能？\",\"三级\"],[\" 网络已经能够保障关键业务数据传输的完整性？\",\"三级\"],[\" 网络已经具有远程配置功能？\",\"三级\"]],\"undone\":[]}}}}\n";
        HashMap<String,HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>> problem2=JSON.parseObject(ps, new TypeReference<HashMap<String,HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>>>(){});

        ssproblem1.put("战略", items);
        ssproblem2.put("人员", items);
        ssproblem3.put("数据", items);
        ssproblem4.put("集成", items);

        sproblem.put("战略", ssproblem1);
        sproblem.put("人员", ssproblem2);
        sproblem.put("数据", ssproblem3);
        sproblem.put("组织战略", ssproblem4);


        problems.put("战略与人员", sproblem);


        HashMap<String, List<String>> suggestions = new HashMap<>();
        List<String> tlist = new ArrayList<>(Arrays.asList(new String[]{
                "建议企业采用多种方式，比如二维码、条形码、RFID、PLC等采集业务活动所需的全部数据，采用传感技术实现制造关键环节数据的自动采集，基于经验对数据进行分析。建立统一的数据编码、数据交换格式和规则等，整合数据资源，支持跨部门的业务协调，实现数据及分析结果在部门内和跨部门的在线共享。",
                "建议企业对关键设备形成技改方案，在关键工序应用自动化设备和数字化设备。关键工序设备具备多种标准统信接口，支持主流通信协议。并且建立关键工序设备的三维模型库。",
        }));
        suggestions.put("组织战略", tlist);
        suggestions.put("网络安全", tlist);


        XWPFDocument doc = openTmpl(tmpl);
        try {
            doc = insertText(doc, textMap);
//            doc=testInsertText2(doc,textMap);
//            doc = insertImage(doc, gscores);
//            doc=insertTable(doc,header,dlist);
            doc = insertProblem(doc, problem2);
//            doc = insertSuggestions(doc, suggestions);
        } catch (Exception e) {
            e.printStackTrace();
        }
        generateDocx(doc, "E:/test.docx");
    }

    public static XWPFDocument openTmpl(String tmpl) {

        XWPFDocument doc = null;
        try {

            //加载文档
            doc = new XWPFDocument( new FileInputStream(tmpl));
            return doc;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return doc;
    }

    public static void generateDocx(XWPFDocument doc, String path) {
        String dirPath = path.substring(0, path.lastIndexOf("/"));
        File dir = new File(dirPath);
        if (!dir.exists())
            dir.mkdirs();
        File file = new File(path);
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(file);
            doc.write(fileOutputStream);
            fileOutputStream.close();
            doc.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {

        }

    }

    public static XWPFDocument insertText(XWPFDocument doc, HashMap<String, String> map)  {

        List<XWPFParagraph> paragraphList = doc.getParagraphs();
        for (XWPFParagraph par : paragraphList) {
            //获取段落的文本对象
            List<XWPFRun> runs = par.getRuns();
            for (XWPFRun run : runs) {
                //获取文本的值
                String text = run.getText(0);
                if (text == null)
                    continue;
                //遍历map
                for (String key : map.keySet()) {
                    //获取map的key

                    //判断文本的值和map的key，文本中是否有和key一样的占位符
                    if (text.indexOf(key) != -1) {
                        //获取对应key的value
                        String value = map.get(key);
                        //把文本的内容，key替换为value
                        text = text.replace(key, value);
                        //把替换好的文本内容，保存到当前这个文本对象
                        run.setText(text, 0);
                    }
                }

            }
        }
        return doc;
    }

    public static XWPFDocument insertSuggestions(XWPFDocument doc, HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>>suggestions){


        List<XWPFParagraph> paragraphList = doc.getParagraphs();
        XWPFParagraph targetPara = null;
        for (XWPFParagraph par : paragraphList) {
            //获取段落的文本对象
            System.out.println(par.getStyle());
            String text = "";
            List<XWPFRun> runs = par.getRuns();
            for (XWPFRun run : runs) {
                //获取文本的值
                text += run.getText(0);

            }
            if (text.indexOf("${suggestions}") != -1) {
                targetPara = par;
                break;

            }
        }
        XmlCursor cursor = null;
        for (String level1 : suggestions.keySet()) {
            cursor = targetPara.getCTP().newCursor();
            XWPFParagraph header1 = doc.insertNewParagraph(cursor);

            for(int i=0;i<targetPara.getRuns().size();i++)
                targetPara.removeRun(i);

            XWPFRun run1 = null;
            List<XWPFRun> runs1 = header1.getRuns();
            if (runs1 == null || runs1.size() == 0) {
                run1 = header1.createRun();
                header1.addRun(run1);
            } else
                run1 = runs1.get(0);
            run1.setText(level1);
            header1.setStyle("2");

            header1.setIndentationLeft(0);
//            run1.addCarriageReturn();

            HashMap<String,HashMap<String, HashMap<String, String>>> subproblems = suggestions.get(level1);
            for (String level2 : subproblems.keySet()) {
                cursor = targetPara.getCTP().newCursor();
                XWPFParagraph header2 = doc.insertNewParagraph(cursor);

                header2.setStyle("3");
                header2.setIndentationLeft(0);
                XWPFRun run2 = null;
                List<XWPFRun> runs2 = header2.getRuns();
                if (runs2 == null || runs2.size() == 0) {
                    run2 = header2.createRun();
                    header2.addRun(run2);
                } else
                    run2 = runs2.get(0);

                run2.setText(level2);
                HashMap<String, HashMap<String, String>> ssubproblems = subproblems.get(level2);
                int index=1;
                for (String level3 : ssubproblems.keySet()) {
                    if(!level2.equals(level3)) {
                        cursor = targetPara.getCTP().newCursor();
                        XWPFParagraph header3 = doc.insertNewParagraph(cursor);
                        header3.setFirstLineIndent(400);
                        XWPFRun run3 = null;
                        List<XWPFRun> runs3 = header3.getRuns();
                        if (runs3 == null || runs3.size() == 0) {
                            run3 = header3.createRun();
                            header3.addRun(run3);
                        } else
                            run3 = runs3.get(0);

                        run3.setText(index+"）"+level3);
                        index++;
                    }
//                run2.addCarriageReturn();
                    HashMap<String, String> items = ssubproblems.get(level3);
                    if(items.containsKey("suggestion")){
                        String done = items.get("suggestion");
                        cursor = targetPara.getCTP().newCursor();
                        XWPFParagraph conent = doc.insertNewParagraph(cursor);
                        conent.setFirstLineIndent(587);
                        conent.setAlignment(ParagraphAlignment.BOTH);
                        XWPFRun crun = null;
                        List<XWPFRun> cruns = conent.getRuns();
                        if (cruns == null || cruns.size() == 0) {
                            crun = conent.createRun();
                            conent.addRun(crun);
                        } else
                            crun = cruns.get(0);
                        crun.setText(done);
                    }

                }
            }

        }
        return doc;
    }


    public static XWPFDocument insertProblem(XWPFDocument doc, HashMap<String, HashMap<String, HashMap<String, HashMap<String, List<List<String>>>>>>problems)  {

        String[] header = {"序号", "问题描述", "等级"};
        List<String> hlist = new ArrayList<>(Arrays.asList(header));


        List<XWPFParagraph> paragraphList = doc.getParagraphs();
        XWPFParagraph targetPara = null;
        for (XWPFParagraph par : paragraphList) {
            //获取段落的文本对象
            System.out.println(par.getStyle());
            String text = "";
            List<XWPFRun> runs = par.getRuns();
            for (XWPFRun run : runs) {
                //获取文本的值
                text += run.getText(0);

            }
            if (text.indexOf("${problems}") != -1) {
                targetPara = par;
                break;

            }
        }
        XmlCursor cursor = null;
        for (String level1 : problems.keySet()) {
            cursor = targetPara.getCTP().newCursor();

            XWPFParagraph header1 = doc.insertNewParagraph(cursor);

            XWPFRun run1 = null;
            List<XWPFRun> runs1 = header1.getRuns();
            if (runs1 == null || runs1.size() == 0) {
                run1 = header1.createRun();
                header1.addRun(run1);
            } else
                run1 = runs1.get(0);
            run1.setText(level1);
            header1.setStyle("2");

            header1.setIndentationLeft(0);
//            run1.addCarriageReturn();

            HashMap<String,HashMap<String, HashMap<String, List<List<String>>>>> subproblems = problems.get(level1);
            for (String level2 : subproblems.keySet()) {
                cursor = targetPara.getCTP().newCursor();
                XWPFParagraph header2 = doc.insertNewParagraph(cursor);

                header2.setStyle("3");
                header2.setIndentationLeft(0);
                XWPFRun run2 = null;
                List<XWPFRun> runs2 = header2.getRuns();
                if (runs2 == null || runs2.size() == 0) {
                    run2 = header2.createRun();
                    header2.addRun(run2);
                } else
                    run2 = runs2.get(0);

                run2.setText(level2);
                HashMap<String, HashMap<String, List<List<String>>>> ssubproblems = subproblems.get(level2);
                for (String level3 : ssubproblems.keySet()) {
                    if(!level2.equals(level3)) {
                        cursor = targetPara.getCTP().newCursor();
                        XWPFParagraph header3 = doc.insertNewParagraph(cursor);

                        header3.setStyle("4");
                        header3.setIndentationLeft(0);
                        XWPFRun run3 = null;
                        List<XWPFRun> runs3 = header3.getRuns();
                        if (runs3 == null || runs3.size() == 0) {
                            run3 = header3.createRun();
                            header3.addRun(run3);
                        } else
                            run3 = runs3.get(0);

                        run3.setText(level3);
                    }
//                run2.addCarriageReturn();
                    HashMap<String, List<List<String>>> items = ssubproblems.get(level3);
                    List<List<String>> dList = items.get("undone");
                    if(dList==null ||dList.size()==0)
                       continue;
                    cursor = targetPara.getCTP().newCursor();
                    XWPFTable table = doc.insertNewTbl(cursor);
                    insertTable(table, hlist, dList);
                }
            }

        }
        return doc;
    }


    public static XWPFDocument insertProblem2(XWPFDocument doc, HashMap<String, HashMap<String, HashMap<String, HashMap<String, String>>>>problems)  {

        List<XWPFParagraph> paragraphList = doc.getParagraphs();
        XWPFParagraph targetPara = null;
        for (XWPFParagraph par : paragraphList) {
            //获取段落的文本对象

            String text = "";
            List<XWPFRun> runs = par.getRuns();
            for (XWPFRun run : runs) {
                //获取文本的值
                text += run.getText(0);

            }
            if (text.indexOf("${problems}") != -1) {
                targetPara = par;
                break;

            }
        }
        XmlCursor cursor = null;
        for (String level1 : problems.keySet()) {
            cursor = targetPara.getCTP().newCursor();
            XWPFParagraph header1 = doc.insertNewParagraph(cursor);

            for(int i=0;i<targetPara.getRuns().size();i++)
                targetPara.removeRun(i);

            XWPFRun run1 = null;
            List<XWPFRun> runs1 = header1.getRuns();
            if (runs1 == null || runs1.size() == 0) {
                run1 = header1.createRun();
                header1.addRun(run1);
            } else
                run1 = runs1.get(0);
            run1.setText(level1);
            header1.setStyle("2");

            header1.setIndentationLeft(0);
//            run1.addCarriageReturn();

            HashMap<String,HashMap<String, HashMap<String, String>>> subproblems = problems.get(level1);
            for (String level2 : subproblems.keySet()) {
                cursor = targetPara.getCTP().newCursor();
                XWPFParagraph header2 = doc.insertNewParagraph(cursor);

                header2.setStyle("3");
                header2.setIndentationLeft(0);
                XWPFRun run2 = null;
                List<XWPFRun> runs2 = header2.getRuns();
                if (runs2 == null || runs2.size() == 0) {
                    run2 = header2.createRun();
                    header2.addRun(run2);
                } else
                    run2 = runs2.get(0);

                run2.setText(level2);
                HashMap<String, HashMap<String, String>> ssubproblems = subproblems.get(level2);
                int index=1;
                for (String level3 : ssubproblems.keySet()) {
                    if(!level2.equals(level3)) {
                        cursor = targetPara.getCTP().newCursor();
                        XWPFParagraph header3 = doc.insertNewParagraph(cursor);
                        header3.setFirstLineIndent(400);
                        XWPFRun run3 = null;
                        List<XWPFRun> runs3 = header3.getRuns();
                        if (runs3 == null || runs3.size() == 0) {
                            run3 = header3.createRun();
                            header3.addRun(run3);
                        } else
                            run3 = runs3.get(0);

                        run3.setText(index+"）"+level3);
                        index++;
                    }
//                run2.addCarriageReturn();
                    HashMap<String, String> items = ssubproblems.get(level3);
                    if(items.containsKey("perfect")){
                    String done = items.get("perfect");
                    cursor = targetPara.getCTP().newCursor();
                    XWPFParagraph conent = doc.insertNewParagraph(cursor);
                    conent.setFirstLineIndent(587);
                    XWPFRun crun = null;
                    List<XWPFRun> cruns = conent.getRuns();
                    if (cruns == null || cruns.size() == 0) {
                        crun = conent.createRun();
                        conent.addRun(crun);
                    } else
                        crun = cruns.get(0);
                    crun.setText(done);
                    }
                    if(items.containsKey("undone")) {
                        String qList = items.get("undone");
                        cursor = targetPara.getCTP().newCursor();
                        XWPFRun qrun = null;
                        XWPFParagraph qconent = doc.insertNewParagraph(cursor);
                        qconent.setAlignment(ParagraphAlignment.BOTH);
                        qconent.setFirstLineIndent(587);
                        List<XWPFRun> qruns = qconent.getRuns();
                        if (qruns == null || qruns.size() == 0) {
                            qrun = qconent.createRun();
                            qconent.addRun(qrun);
                        } else
                            qrun = qruns.get(0);
                        qconent.addRun(qrun);
                        qrun.setText(qList);
                    }
                }
            }

        }
        return doc;
    }

    public static List<String> getImageString(XWPFDocument doc) {
        List<String> items = new ArrayList<>();
        List<XWPFParagraph> paragraphList = doc.getParagraphs();
        //遍历段落
        for (XWPFParagraph par : paragraphList) {
            String item = par.getText();
            if (item != null) {
                item = item.trim();
                if (item.startsWith("${pic")) {
                    if(items.contains(item))
                        continue;
                    items.add(item);
                }
            }

        }
        return items;
    }

    public static XWPFDocument insertImage(XWPFDocument doc, Map<String, HashMap<String, Double>> map) throws Exception {
       HashMap<XWPFParagraph,String> pars= new HashMap<>();


        //遍历段落
        for (XWPFParagraph par : doc.getParagraphs()) {
            String item = par.getText();
            if (item != null) {
                item = item.trim();
                if (item.startsWith("${pic")) {
                    pars.put(par,item);
                }
            }

        }
        for(XWPFParagraph par:pars.keySet()){
            for(int i=0;i<par.getRuns().size();i++)
                par.removeRun(i);
            XmlCursor cursor = par.getCTP().newCursor();
            XWPFParagraph ipar=doc.insertNewParagraph(cursor);
            ipar.setAlignment(ParagraphAlignment.CENTER);
            HashMap<String, Double> data = map.get(pars.get(par));
            HashMap<String, HashMap<String, Double>> rdata = new HashMap<>();
            rdata.put(pars.get(par), data);

            //获取对应key的value
            InputStream value = RadarUtil.bufferedImageToInputStream(rdata);
            XWPFRun run = ipar.createRun();
//            run.addBreak();
            String picPath = value.toString();
            try {
                XWPFPicture pic = run.addPicture(value, Document.PICTURE_TYPE_PNG, picPath, Units.toEMU(300), Units.toEMU(300));

                value.close();
                ipar.addRun(run);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


        return doc;
    }


    public static void insertTable(XWPFTable table, List<String> headers, List<List<String>> dList) {
        if(dList==null ||dList.size()==0)
            return;
        XWPFTableRow hrow = table.getRow(0);
        if (hrow == null)
            hrow = table.createRow();
        for (int i = 0; i < headers.size(); i++) {
            //添加一个新行
            XWPFTableCell cell = hrow.getCell(i);
            if (cell == null)
                cell = hrow.createCell();
            cell.setText(headers.get(i));

            XWPFParagraph para = cell.getParagraphs().get(0);
            XWPFRun run = null;
            if (para.getRuns() == null) {
                run = para.createRun();
                para.addRun(run);
            } else {
                run = para.getRuns().get(0);
            }

            run.setFontFamily("宋体");
            run.setFontSize(12);
            run.setBold(true);
            para.setAlignment(ParagraphAlignment.CENTER);
            para.setIndentationFirstLine(0);
            para.setFirstLineIndent(0);
            para.setIndentationHanging(0);
            para.setIndentationLeft(0);
           // para.setIndentationLeftChars(0);

        }

        //创建行,根据需要插入的数据添加新行，不处理表头
        for (int i = 0; i < dList.size(); i++) {
            List<String> data = dList.get(i);
            XWPFTableRow drow = table.createRow();
            XWPFTableCell cell0 = drow.getCell(0);
            if (cell0 == null)
                cell0 = drow.createCell();
            cell0.setText((i+1)+"");
            cell0.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
            XWPFParagraph para0 = cell0.getParagraphs().get(0);
            para0.setAlignment(ParagraphAlignment.CENTER);
            para0.setIndentationFirstLine(0);
            for (int j = 0; j < data.size(); j++) {
                XWPFTableCell cell = drow.getCell(j+1);
                if (cell == null)
                    cell = drow.createCell();
                cell.setText(data.get(j));
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                XWPFParagraph para = cell.getParagraphs().get(0);

                XWPFRun run = null;
                if (para.getRuns() == null) {
                    run = para.createRun();
                    para.addRun(run);
                } else {
                    run = para.getRuns().get(0);
                }
                run.setFontFamily("宋体");
                run.setFontSize(12);
                para.setAlignment(ParagraphAlignment.LEFT);
                para.setIndentationFirstLine(0);
            }
        }
        CTTblPr tblPr = table.getCTTbl().getTblPr();
        tblPr.getTblW().setType(STTblWidth.DXA);
        tblPr.getTblW().setW(new BigInteger("8000"));
        CTTblLayoutType t = tblPr.isSetTblLayout() ? tblPr.getTblLayout() : tblPr.addNewTblLayout();
        t.setType(STTblLayoutType.FIXED);
        CTTblGrid ctTblGrid = table.getCTTbl().getTblGrid() != null ? table.getCTTbl().getTblGrid() : table.getCTTbl().addNewTblGrid();
        ctTblGrid.addNewGridCol().setW(BigInteger.valueOf(1000));
        ctTblGrid.addNewGridCol().setW(BigInteger.valueOf(6000));
        ctTblGrid.addNewGridCol().setW(BigInteger.valueOf(1000));


    }

    public static XWPFDocument insertTable(XWPFDocument doc, List<List<String>> dList, int index) {
        XWPFTable table = doc.getTables().get(index);
        //创建行,根据需要插入的数据添加新行，不处理表头
        for (int i = 0; i < dList.size(); i++) {
            List<String> data = dList.get(i);
            XWPFTableRow drow = table.createRow();
            for (int j = 0; j < data.size(); j++) {
                XWPFTableCell cell = drow.getCell(j);
                if (cell == null)
                    cell = drow.createCell();
                cell.setText(data.get(j));
                XWPFParagraph p = cell.getParagraphs().get(0);
                XWPFRun run = p.getRuns().get(0);
                run.setFontFamily("仿宋");

//
//                CTTcPr ctPr = cell.getCTTc().addNewTcPr();
//                ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                cell.getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
            }
        }


        return doc;
    }


}
